﻿#include <cstring>
#include <iostream>
#include <array>
#include <functional>

/*
 * 虚函数实现多态。非常简单，派生类重写基类的虚函数即可
 * 多态调用的时候会有一次虚函数的调用, 会产生额外的开销,
 * 虽然一般情况下这个虚函数调用的开销非常小可以忽略不计,
 * 但是在某些对性能要求非常高的场景下还是希望消除这个虚函数的开销, 把性能优化到极致
 */

 /*
  * 通过函数指针而不是虚函数来实现多态调用, 在基类中保存一个函数指针,
  * 派生类构造的时候去初始化这个函数指针,让它指向派生类的一个静态函数,
  * 通过静态函数去扩展基类的函数, 从而实现非虚函数的多态调用。
 */

struct base_t {
	using FuncType = void (*)(void*, int);
	//using FuncType = std::function<void(void*, int)>;

	base_t(base_t::FuncType func = nullptr): func_(func) {}

	void perform(int val) {
		if (func_)	func_(this, val);
		else throw std::runtime_error{"None exigst function"};
	}

private:
	FuncType func_;
};

struct derived1: public base_t {
	derived1(): base_t(derived1::do_perform) {}
	void perform(int val) {
		int r = val * 2;
	}
private:
	static void do_perform(void* owner, int val) {
		int r = val * 2;
	}
};

struct derived2: public base_t {
	derived2(): base_t(derived2::do_perform) {}
	void perform(int val) {
		int r = val * 3;
	}

private:
	static void do_perform(void* owner, int val) {
		int r = val * 3;
	}
};
// 函数指针实现多态
void test1() {

	derived1 d{};
	derived2 d2{};
	std::array<base_t*, 2> vec{ &d, & d2 };
	for (auto b : vec) {
		b->perform(42); // 非虚函数调用，调用函数指针
	}
}

//静态多态

template<class Impl>
struct base1 {
	template<class Buffer, class... Args>
	void read_some(Buffer buf, Args &&...args) {
		impl_.read_some(std::forward<Buffer>(buf)
			, std::forward<Args>(args)...);
	}
	Impl impl_;
};
struct derived_obj {
	/*
	* 函数需要重载多个，否则模板方法调用会找不到函数
	*/
	void read_some(const std::string &buf) {
		std::cout << "read string\n";
	}

	void read_some(const std::string& buf, int size) {
		std::cout << "read string, size " << size << "\n";
	}
};

void test2()
{
	base1<derived_obj> d1{};

	char buf[] = { "hello" };
	// 调用模板方法
	d1.read_some(buf);
	d1.read_some(buf, 42);
	// std::vector<char> vecbuf{buf, buf + 5};
	// d1.read_some(vecbuf, 42); // [error C2665] 编译报错。没有匹配的函数
}


// 上帝接口
template<typename Op, typename Buffer, typename... Args>
void god_operation_interface(Op&& op, const Buffer& buf, Args &&...args) {
	op(buf, args...);
}

struct drived_god {
	struct read_some_init { 
		void operator()(std::string buf) const {
			std::cout << "read string\n"; 
		}

		void operator()(std::string buf, int size) const {
			std::cout << "read string, size " << size << "\n";
		}
	};

	struct write_some_init {
		void operator()(std::string buf) {
			std::cout << "write string\n";
		}
	};

	void read_some(std::string buf) {
		god_operation_interface(read_some_init{}, buf);
	}

	void read_some(std::string buf, int size) {
		god_operation_interface(read_some_init{}, buf, size);
	}

	void write_some(std::string buf) {
		god_operation_interface(write_some_init{}, buf);
	}
};
void test3()
{
	drived_god god;
	god.read_some("hello");
	god.read_some("hello", strlen("hello"));
	god.write_some("world");
}



int main() {

	test1();
	test2();
}
